package com.controller;

import com.vo.Student;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

//把属性添加到request作用域的同时添加到session作用域，可以以名字或类型添加
@SessionAttributes("stu2")
//@SessionAttributes(types = Student.class)
//@SessionAttributes(value = {"stu2","stu1"},types = {Student.class})
@Controller
@RequestMapping("/view")
public class ModelAndViewController {

    /**
     * ModelAndView 视图和模型
     *  本身的参数就是jsp的名字
     * @param gender
     * @return
     */
    @RequestMapping("/modelAndView")
    public ModelAndView modelData_mav(String gender){

        // 创建一个 模型视图对象
        //  可以无参后续使用setViewName进行设置
        //  比较适合根据不同情况进入到不同页面的情景使用
        //  或者可以直接以参数的形式把页面名设置进去
        ModelAndView modelAndView = new ModelAndView();

        //相当于 modelAndView.addObject("string","男)
        //一般不建议使用，因为只能有一个同类型的数据，获取数据的key也不方便
        modelAndView.addObject(gender);
        //添加普通键值对形式的数据
        modelAndView.addObject("name","tom");

        //一个Map中可以存储多个键值对
        Map<String,Object> objMap = new HashMap<>();
        objMap.put("salary",10000);
        objMap.put("address","哈尔滨");

        //可以以Map为参数，一次性添加多个键值对
        modelAndView.addAllObjects(objMap);

        //不同的条件可以进入到不同的页面
        if(gender.equals("男")){
            modelAndView.setViewName("boyEmp");
        }else{
            modelAndView.setViewName("girlEmp");
        }

        return modelAndView;

    }

    /**
     * Model 模型，没有视图
     *  视图还需要以字符串形式表示
     * @param model  是一个接口，要以参数的形式存在
     * @param gender
     * @return
     */
    @RequestMapping("/model")
    public String modelData_model(Model model,String gender){

        String view = "";

        //相当于 model.addAttribute("string","男");
        model.addAttribute(gender);
        //添加普通的键值对
        model.addAttribute("name","jerry");

        //一个Map中可以存储多个键值对
        Map<String,Object> objMap = new HashMap<>();
        objMap.put("salary",10000);
        objMap.put("address","哈尔滨");

        //以Map的形式一次性添加多个键值对
        model.addAllAttributes(objMap);

        //根据不同的条件进入到不同的页面
        if(gender.equals("男")){
            view = "boyEmp";
        }else{
            view = "girlEmp";
        }

        return view;
    }

    @RequestMapping("/map")
    public String ModelData_map(Map map,String gender){

        String view = "";

        //添加单条的键值对数据
        map.put("gender",gender);
        map.put("name","kitty");

        //一个Map中可以存储多个键值对
        Map<String,Object> objMap = new HashMap<>();
        objMap.put("salary",10000);
        objMap.put("address","哈尔滨");

        //一次性添加多个键值对数据
        map.putAll(objMap);

        //根据不同的条件进入到不同的页面
        if(gender.equals("男")){
            view = "boyEmp";
        }else{
            view = "girlEmp";
        }

        return view;
    }

    /**
     * 1. @ModelAttribute 不显示使用，也会向model中添加属性值
     * 参数是pojo,相当于默认提供了一个Model
     * 自动的添加了一个键值对(pojo类的首字母小写,此对象)
     * @param student1
     * @return
     */
    @RequestMapping("/modelAttr1")
    public String modelData_ModelAttr1(Student student1){

        student1.setStuName("tom");
        student1.setAge(100);

        return "studentInfo";
    }

    /**
     * modelData_ModelAttr1 方法的显示使用方式
     * 好处就是可以自定义key的名字
     * 缺点就是代码稍微多了一点
     * @param model
     * @return
     */
    @RequestMapping("/modelAttr2")
    public String modelData_ModelAttr2(Model model){

        Student student = new Student();
        student.setStuName("tom");
        student.setAge(100);

        model.addAttribute("stu",student);

        return "studentInfo";
    }

    /**
     * 2. @ModelAttribute 与 @RequestMapping 分开使用
     * 相当于 model.addAttribute(key,value)
     * 单独的 @ModelAttribute 先于 @RequestMapping 执行
     * 对此类中的所有  @RequestMapping 都生效
     */

    // 2.1 返回值为 void 且  @ModelAttribute 无参的情况
    @ModelAttribute
    public void studentMap(Map<String,Object> stuMap){
        Student stu = new Student();
        stu.setStuName("张添齐");
        stu.setAge(10);
        stuMap.put("stu",stu);
    }

    @ModelAttribute
    public void studentModel(Model model){
        Student stu = new Student();
        stu.setStuName("徐豪");
        stu.setAge(20);
        model.addAttribute("stu1",stu);
    }

    /**
     * 2.2 返回的类型是Pojo类型，@ModelAttribute 没有参数
     *     在页面接收的时候，是以pojo类名小写的形式获取
     * @return
     */
    @ModelAttribute
    public Student studentPojoNoParam(){
        Student stu = new Student();
        stu.setStuName("开祥鹏");
        stu.setAge(22);
        return stu;
    }

    /**
     * 2.3 返回的类型是Pojo类型，@ModelAttribute 有参数
     *     在页面接收的时候，可以以参数为key进行接收
     * @return
     */
    @ModelAttribute("stu2")
    public Student studentPojoParam(){
        Student stu = new Student();
        stu.setStuName("赵圣骏");
        stu.setAge(18);
        return stu;
    }

    @RequestMapping("/modelAttr3")
    public String modelData_ModelAttr3(Model model){
        return "studentInfo";
    }

    /**
     * 3. 如果@ModelAttribute与@RequestMapping 共同使用
     * 返回的字符串不再是jsp页面，是request作用域下的值 以
     *  @ModelAttribute属性名为key 以 return 的内容为 value 携带数据进入页面
     *  @RequestMapping 的参数作为进入的jsp页面名字
     * @return
     */
    @RequestMapping("/studentInfo")
    @ModelAttribute("cute")
    public String modelData_ModelAttr4(){
        return "@^-^@";
    }


    /**
     * 4.把 @ModelAttribute 注解定义的属性带入当前方法的参数中
     * 先加载@ModelAttribute中的对象，如果页面中也有此对象，页面中的对象会覆盖掉@ModelAttribute对象
     * @param student
     * @return
     */
    @RequestMapping("/modelAttr5")
    public String modelData_ModelAttr5(@ModelAttribute("stu2") Student student){
        System.out.println(student);
        return "studentInfo";
    }


}
